/* -*-c++-*- */
/* osgGIS - GIS Library for OpenSceneGraph
 * Copyright 2007-2008 Glenn Waldron and Pelican Ventures, Inc.
 * http://osggis.org
 *
 * osgGIS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#ifndef _OSGGIS_FILTER_STATE_H_
#define _OSGGIS_FILTER_STATE_H_ 1

#include <osgGIS/Common>
#include <osgGIS/FilterEnv>
#include <osgGIS/Report>

namespace osgGIS
{
    class Filter;
    class FilterFactory;

    /*(internal)
     * Transmits a result state for a filter state operation
     */
    class FilterStateResult
    {
    public:
        enum Status {
            STATUS_NONE,
            STATUS_ERROR,
            STATUS_NODATA
        };

        bool isOK() const { return status != STATUS_ERROR; }
        bool isError() const { return status == STATUS_ERROR; }
        bool isNoData() const { return status == STATUS_NODATA; }
        bool hasData() const { return isOK() && !isNoData(); }
        Status getStatus() const { return status; }
        const std::string& getMessage() const { return msg; }
        Filter* getFilter() const { return filter.get(); }

    public:
        FilterStateResult();
        FilterStateResult( const FilterStateResult& rhs );
        FilterStateResult( Status status, Filter* filter =NULL, const std::string& msg ="" );

        void set( Status status, Filter* filter =NULL, const std::string& msg ="" );

    private:
        Status status;
        std::string msg;
        osg::ref_ptr<Filter> filter;
    };

    /* (no api docs)
     * Maintains the flow of data through a filter.
     */
    class FilterState : public osg::Referenced
    {
    public:
        /**
         * Runs the filter logic within the contextual environment, pushing the
         * filter's output to the next filter in the chain.
         *
         * @param env
         *      Contextual compilation environment.
         * @return
         *      True if traversal succeeded, false upon error.
         */
        virtual FilterStateResult traverse( FilterEnv* env ) =0;

        /** 
         * Notifies this filter that a compilation checkpoint has been reached.
         * This supports batching/metering of data by CollectionFilters.
         *
         * @return
         *      True if traversal succeeded, false upon error.
         */
        virtual FilterStateResult signalCheckpoint();
        
        /**
         * Gets the next filter state in the chain.
         */
        FilterState* getNextState();

        /**
         * Gets a reference to the last filter environment object that passed
         * through this filter.
         *
         * @return A filter environment
         */
        FilterEnv* getLastKnownFilterEnv();

        /**
         * Gets the report associated with this object.
         *
         * @return A Report
         */
        Report* getReport() const;

    protected:    
        FilterState();

        osg::ref_ptr<FilterState> next_state;
        osg::ref_ptr<Filter> filter_prototype;
        std::string name;
        osg::ref_ptr<FilterEnv> current_env;
        osg::ref_ptr<Report> report;
        
        friend class FilterGraph;
        FilterState* setNextState( FilterState* state );
        FilterState* appendState( FilterState* state );
    };
}

#endif // _OSGGIS_FILTER_STATE_H_
